home *** CD-ROM | disk | FTP | other *** search
- ╒═══════════════════════════════╕
- │ W E L C O M E │
- │ To the VGA Trainer Program │ │
- │ By │ │
- │ DENTHOR of ASPHYXIA │ │ │
- ╘═══════════════════════════════╛ │ │
- ────────────────────────────────┘ │
- ────────────────────────────────┘
-
- --==[ PART 8 ]==--
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Introduction
-
- Hello everybody! Christmas is over, the last of the chocolates have been
- eaten, so it's time to get on with this, the eighth part of the ASPHYXIA
- Demo Trainer Series. This particular part is primarily about 3-D, but
- also includes a bit on optimisation.
-
- If you are already a 3-D guru, you may as well skip this text file, have
- a quick look at the sample program then go back to sleep, because I am
- going to explain in minute detail exactly how the routines work ;)
-
- If you would like to contact me, or the team, there are many ways you
- can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
- on the ASPHYXIA BBS.
- 2) Write a message in the Programming conference on the
- For Your Eyes Only BBS (of which I am the Moderator )
- This is preferred if you have a general programming query
- or problem others would benefit from.
- 4) Write to Denthor, EzE or Goth on Connectix.
- 5) Write to : Grant Smith
- P.O.Box 270 Kloof
- 3640
- Natal
- 6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
- call during varsity)
- 7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
- mention the word Denthor near the top of the letter.
-
- NB : If you are a representative of a company or BBS, and want ASPHYXIA
- to do you a demo, leave mail to me; we can discuss it.
- NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
- quite lonely and want to meet/help out/exchange code with other demo
- groups. What do you have to lose? Leave a message here and we can work
- out how to transfer it. We really want to hear from you!
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Optimisation
-
- Before I begin with the note on 3-D, I would like to stress that many of
- these routines, and probably most of your own, could be sped up quite a
- bit with a little optimisation. One must realise, however, that you must
- take a look at WHAT to optimise ... converting a routine that is only
- called once at startup into a tightly coded assembler routine may show
- off your merits as a coder, but does absolutely nothing to speed up your
- program. Something that is called often per frame is something that
- needs to be as fast as possible. For some, a much used procedure is the
- PutPixel procedure. Here is the putpixel procedure I gave you last week:
-
- Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
- BEGIN
- Asm
- push ds { 14 clock ticks }
- push es { 14 }
- mov ax,[where] { 8 }
- mov es,ax { 2 }
- mov bx,[X] { 8 }
- mov dx,[Y] { 8 }
- push bx { 15 }
- mov bx, dx { 2 }
- mov dh, dl { 2 }
- xor dl, dl { 3 }
- shl bx, 1 { 2 }
- shl bx, 1 { 2 }
- shl bx, 1 { 2 }
- shl bx, 1 { 2 }
- shl bx, 1 { 2 }
- shl bx, 1 { 2 }
- add dx, bx { 3 }
- pop bx { 12 }
- add bx, dx { 3 }
- mov di, bx { 2 }
- xor al,al { 3 }
- mov ah, [Col] { 8 }
- mov es:[di],ah { 10 }
- pop es { 12 }
- pop ds { 12 }
- End;
- END;
- Total = 153 clock ticks
- NOTE : Don't take my clock ticks as gospel, I probably got one or two
- wrong.
-
- Right, now for some optimising. Firstly, if you have 286 instructions
- turned on, you may replace the 6 shl,1 with shl,6. Secondly, the Pascal
- compiler automatically pushes and pops ES, so those two lines may be
- removed. DS:[SI] is not altered in this procedure, so we may remove
- those too. Also, instead of moving COL into ah, we move it into AL and
- call stosb (es:[di]:=al; inc di). Let's have a look at the routine now :
-
- Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
- BEGIN
- Asm
- mov ax,[where] { 8 }
- mov es,ax { 2 }
- mov bx,[X] { 8 }
- mov dx,[Y] { 8 }
- push bx { 15 }
- mov bx, dx { 2 }
- mov dh, dl { 2 }
- xor dl, dl { 3 }
- shl bx, 6 { 8 }
- add dx, bx { 3 }
- pop bx { 12 }
- add bx, dx { 3 }
- mov di, bx { 2 }
- mov al, [Col] { 8 }
- stosb { 11 }
- End;
- END;
- Total = 95 clock ticks
-
- Now, let us move the value of BX directly into DI, thereby removing a
- costly push and pop. The MOV and the XOR of DX can be replaced by it's
- equivalent, SHL DX,8
-
- Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
- asm
- mov ax,[where] { 8 }
- mov es,ax { 2 }
- mov bx,[X] { 8 }
- mov dx,[Y] { 8 }
- mov di,bx { 2 }
- mov bx, dx { 2 }
- shl dx, 8 { 8 }
- shl bx, 6 { 8 }
- add dx, bx { 3 }
- add di, dx { 3 }
- mov al, [Col] { 8 }
- stosb { 11 }
- end;
- Total = 71 clock ticks
-
- As you can see, we have brought the clock ticks down from 153 ticks to
- 71 ticks ... quite an improvement. (The current ASPHYXIA putpixel takes
- 48 clock ticks) . As you can see, by going through your routines a few
- times, you can spot and remove unnecessary instructions, thereby greatly
- increasing the speed of your program.
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Defining a 3-D object
-
- Drawing an object in 3-D is not that easy. Sitting down and plotting a
- list of X,Y and Z points can be a time consuming business. So, let us
- first look at the three axes you are drawing them on :
-
- Y Z
- /|\ /
- | /
- X<-----|----->
- |
- \|/
-
- X is the horisontal axis, from left to right. Y is the vertical axis,
- from top to bottom. Z is the depth, going straight into the screen.
-
- In this trainer, we are using lines, so we define 2 X,Y and Z
- coordinates, one for each end of the line. A line from far away, in the
- upper left of the X and Y axes, to close up in the bottom right of the
- X and Y axes, would look like this :
-
- { x1 y1 z1 x2 y2 z2 }
- ( (-10,10,-10),(10,-10,10) )
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Rotating a point with matrixes
-
- NOTE : I thought that more then one matix are matrisese (sp), but my
- spellchecker insists it is matrixes, so I let it have it's way
- ;-)
-
- Having a 3-D object is useless unless you can rotate it some way. For
- demonstration purposes, I will begin by working in two dimensions, X and
- Y.
-
- Let us say you have a point, A,B, on a graph.
- Y
- | /O1 (Cos (a)*A-Sin (a)*B , Sin (a)*A+Cos (a)*B)
- |/ (A,B)
- X<-----|------O-->
- |
- |
-
- Now, let us say we rotate this point by 45 degrees anti-clockwise. The
- new A,B can be easily be calculated using sin and cos, by an adaption of
- our circle algorithm, ie.
- A2:=Cos (45)*A - Sin (45)*B
- B2:=Sin (45)*A + Cos (45)*B
- I recall that in standard 8 and 9, we went rather heavily into this in
- maths. If you have troubles, fine a 8/9/10 maths book and have a look;
- it will go through the proofs etc.
-
- Anyway, we have now rotated an object in two dimensions, AROUND THE Z
- AXIS. In matrix form, the equation looks like this :
-
- [ Cos (a) -Sin (a) 0 0 ] [ x ]
- [ Sin (a) Cos (a) 0 0 ] . [ y ]
- [ 0 0 1 0 ] [ z ]
- [ 0 0 0 1 ] [ 1 ]
-
- I will not go to deeply into matrixes math at this stage, as there are
- many books on the subject (it is not part of matric maths, however). To
- multiply a matrix, to add the products of the row of the left matrix and
- the column of the right matrix, and repeat this for all the columns of the
- left matrix. I don't explain it as well as my first year maths lecturer,
- but have a look at how I derived A2 and B2 above. Here are the other
- matrixes :
-
- Matrix for rotation around the Y axis :
- [ Cos (a) 0 -Sin (a) 0 ] [ x ]
- [ 0 1 0 0 ] . [ y ]
- [ Sin (a) 0 Cos (a) 0 ] [ z ]
- [ 0 0 0 1 ] [ 1 ]
-
- Matrix for rotation around the X axis :
- [ 1 0 0 ] [ x ]
- [ 0 Cos (a) -Sin (a) 0 ] . [ y ]
- [ 0 Sin (a) Cos (a) 0 ] [ z ]
- [ 0 0 0 1 ] [ 1 ]
-
- By putting all these matrixes together, we can translate out 3D points
- around the origin of 0,0,0. See the sample program for how we put them
- together.
-
- In the sample program, we have a constant, never changing base object.
- This is rotated into a second variable, which is then drawn. I am sure
- many of you can thing of cool ways to change the base object, the
- effects of which will appear while the object is rotating. One idea is
- to "pulsate" a certain point of the object according to the beat of the
- music being played in the background. Be creative. If you feel up to it,
- you could make your own version of transformers ;)
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Drawing a 3D point to screen
-
- Having a rotated 3D object is useless unless we can draw it to screen.
- But how do we show a 3D point on a 2D screen? The answer needs a bit of
- explaining. Examine the following diagram :
-
- | ________-------------
- ____|___------ o Object at X,Y,Z o1 Object at X,Y,Z2
- Eye -> O)____|___
- | ------________
- | -------------- Field of vision
- Screen
-
- Let us pretend that the centre of the screen is the horizon of our
- little 3D world. If we draw a three dimensional line from object "o" to
- the centre of the eye, and place a pixel on the X and Y coordinates
- where it passes through the screen, we will notice that when we do the
- same with object o1, the pixel is closer to the horizon, even though
- their 3D X and Y coords are identical, but "o1"'s Z is larger then
- "o"'s. This means that the further away a point is, the closer to the
- horizon it is, or the smaller the object will appear. That sounds
- right, doesent it? But, I hear you cry, how do we translate this into a
- formula? The answer is quite simple. Divide your X and your Y by your Z.
- Think about it. The larger the number you divide by, the closer to zero,
- or the horizon, is the result! This means, the bigger the Z, the
- further away is the object! Here it is in equation form :
-
- nx := 256*x div (z-Zoff)+Xoff
- ny := 256*y div (z-Zoff)+Yoff
-
- NOTE : Zoff is how far away the entire object is, Xoff is the objects X
- value, and Yoff is the objects Y value. In the sample program,
- Xoff start off at 160 and Yoff starts off at 100, so that the
- object is in the middle of the screen.
-
- The 256 that you times by is the perspective with which you are viewing.
- Changing this value gives you a "fish eye" effect when viewing the
- object. Anyway, there you have it! Draw a pixel at nx,ny, and viola! you
- are now doing 3D! Easy, wasn't it?
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Possible improvements
-
- This program is not the most optimised routine you will ever encounter
- (;-)) ... it uses 12 muls and 2 divs per point. (Asphyxia currently has
- 9 muls and 2 divs per point) Real math is used for all the calculations
- in the sample program, which is slow, so fixed point math should be
- implemented (I will cover fixed point math in a future trainer). The
- line routine currently being used is very slow. Chain-4 could be used to
- cut down on screen flipping times.
-
- Color values per line should be added, base object morphing could be put
- in, polygons could be used instead of lines, handling of more then one
- object should be implemented, clipping should be added instead of not
- drawing something if any part of it is out of bounds.
-
- In other words, you have a lot of work ahead of you ;)
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ In closing
-
- There are a lot of books out there on 3D, and quite a few sample
- programs too. Have a look at them, and use the best bits to create your
- own, unique 3D engine, with which you can do anything you want. I am
- very interested in 3D (though EzE and Goth wrote most of ASPHYXIA'S 3D
- routines), and would like to see what you can do with it. Leave me a
- message through one of the means described above.
-
- I am delving into the murky world of texture mapping. If anyone out
- there has some routines on the subject and are interested in swapping,
- give me a buzz!
-
- What to do in future trainers? Help me out on this one! Are there any
- effects/areas you would like a bit of info on? Leave me a message!
-
- I unfortunately did not get any messages regarding BBS's that carry this
- series, so the list that follows is the same one from last time. Give
- me your names, sysops!
-
- Aaaaargh!!! Try as I might, I can't think of a new quote. Next time, I
- promise! ;-)
-
- Bye for now,
- - Denthor
-
-
- These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
-
- ╔══════════════════════════╦════════════════╦═════╦═══╦════╦════╗
- ║BBS Name ║Telephone No. ║Open ║Msg║File║Past║
- ╠══════════════════════════╬════════════════╬═════╬═══╬════╬════╣
- ║ASPHYXIA BBS #1 ║(031) 765-5312 ║ALL ║ * ║ * ║ * ║
- ║ASPHYXIA BBS #2 ║(031) 765-6293 ║ALL ║ * ║ * ║ * ║
- ║Connectix BBS ║(031) 266-9992 ║ALL ║ * ║ ║ ║
- ║For Your Eyes Only BBS ║(031) 285-318 ║A/H ║ * ║ * ║ * ║
- ╚══════════════════════════╩════════════════╩═════╩═══╩════╩════╝
-
- Open = Open at all times or only A/H
- Msg = Available in message base
- File = Available in file base
- Past = Previous Parts available
- {$X+}
- USES Crt;
-
- CONST VGA = $A000;
- MaxLines = 12;
- Obj : Array [1..MaxLines,1..2,1..3] of integer =
- (
- ((-10,-10,-10),(10,-10,-10)),((-10,-10,-10),(-10,10,-10)),
- ((-10,10,-10),(10,10,-10)),((10,-10,-10),(10,10,-10)),
- ((-10,-10,10),(10,-10,10)),((-10,-10,10),(-10,10,10)),
- ((-10,10,10),(10,10,10)),((10,-10,10),(10,10,10)),
- ((-10,-10,10),(-10,-10,-10)),((-10,10,10),(-10,10,-10)),
- ((10,10,10),(10,10,-10)),((10,-10,10),(10,-10,-10))
- ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
- { (X2,Y2,Z2) ... for the two ends of a line }
-
-
- Type Point = Record
- x,y,z:real; { The data on every point we rotate}
- END;
- Virtual = Array [1..64000] of byte; { The size of our Virtual Screen }
- VirtPtr = ^Virtual; { Pointer to the virtual screen }
-
-
- VAR Lines : Array [1..MaxLines,1..2] of Point; { The base object rotated }
- Translated : Array [1..MaxLines,1..2] of Point; { The rotated object }
- Xoff,Yoff,Zoff:Integer; { Used for movement of the object }
- lookup : Array [0..360,1..2] of real; { Our sin and cos lookup table }
- Virscr : VirtPtr; { Our first Virtual screen }
- Vaddr : word; { The segment of our virtual screen}
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure SetMCGA; { This procedure gets you into 320x200x256 mode. }
- BEGIN
- asm
- mov ax,0013h
- int 10h
- end;
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure SetText; { This procedure returns you to text mode. }
- BEGIN
- asm
- mov ax,0003h
- int 10h
- end;
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Cls (Where:word;Col : Byte);
- { This clears the screen to the specified color }
- BEGIN
- asm
- push es
- mov cx, 32000;
- mov es,[where]
- xor di,di
- mov al,[col]
- mov ah,al
- rep stosw
- pop es
- End;
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure SetUpVirtual;
- { This sets up the memory needed for the virtual screen }
- BEGIN
- GetMem (VirScr,64000);
- vaddr := seg (virscr^);
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure ShutDown;
- { This frees the memory used by the virtual screen }
- BEGIN
- FreeMem (VirScr,64000);
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- procedure flip(source,dest:Word);
- { This copies the entire screen at "source" to destination }
- begin
- asm
- push ds
- mov ax, [Dest]
- mov es, ax
- mov ax, [Source]
- mov ds, ax
- xor si, si
- xor di, di
- mov cx, 32000
- rep movsw
- pop ds
- end;
- end;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Pal(Col,R,G,B : Byte);
- { This sets the Red, Green and Blue values of a certain color }
- Begin
- asm
- mov dx,3c8h
- mov al,[col]
- out dx,al
- inc dx
- mov al,[r]
- out dx,al
- mov al,[g]
- out dx,al
- mov al,[b]
- out dx,al
- end;
- End;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Function rad (theta : real) : real;
- { This calculates the degrees of an angle }
- BEGIN
- rad := theta * pi / 180
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure SetUpPoints;
- { This sets the basic offsets of the object, creates the lookup table and
- moves the object from a constant to a variable }
- VAR loop1:integer;
- BEGIN
- Xoff:=160;
- Yoff:=100;
- Zoff:=-256;
- For loop1:=0 to 360 do BEGIN
- lookup [loop1,1]:=sin (rad (loop1));
- lookup [loop1,2]:=cos (rad (loop1));
- END;
- For loop1:=1 to MaxLines do BEGIN
- Lines [loop1,1].x:=Obj [loop1,1,1];
- Lines [loop1,1].y:=Obj [loop1,1,2];
- Lines [loop1,1].z:=Obj [loop1,1,3];
- Lines [loop1,2].x:=Obj [loop1,2,1];
- Lines [loop1,2].y:=Obj [loop1,2,2];
- Lines [loop1,2].z:=Obj [loop1,2,3];
- END;
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
- { This puts a pixel on the screen by writing directly to memory. }
- BEGIN
- Asm
- mov ax,[where]
- mov es,ax
- mov bx,[X]
- mov dx,[Y]
- mov di,bx
- mov bx, dx {; bx = dx}
- shl dx, 8
- shl bx, 6
- add dx, bx {; dx = dx + bx (ie y*320)}
- add di, dx {; finalise location}
- mov al, [Col]
- stosb
- End;
- END;
-
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure Line(a,b,c,d:integer;col:byte;where:word);
- { This draws a solid line from a,b to c,d in colour col }
- function sgn(a:real):integer;
- begin
- if a>0 then sgn:=+1;
- if a<0 then sgn:=-1;
- if a=0 then sgn:=0;
- end;
- var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
- begin
- u:= c - a;
- v:= d - b;
- d1x:= SGN(u);
- d1y:= SGN(v);
- d2x:= SGN(u);
- d2y:= 0;
- m:= ABS(u);
- n := ABS(v);
- IF NOT (M>N) then
- BEGIN
- d2x := 0 ;
- d2y := SGN(v);
- m := ABS(v);
- n := ABS(u);
- END;
- s := m shr 1;
- FOR i := 0 TO m DO
- BEGIN
- putpixel(a,b,col,where);
- s := s + n;
- IF not (s<m) THEN
- BEGIN
- s := s - m;
- a:= a + d1x;
- b := b + d1y;
- END
- ELSE
- BEGIN
- a := a + d2x;
- b := b + d2y;
- END;
- end;
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure DrawLogo;
- { This draws 'ASPHYXIA' at the top of the screen in little balls }
- CONST ball : Array [1..5,1..5] of byte =
- ((0,1,1,1,0),
- (1,4,3,2,1),
- (1,3,3,2,1),
- (1,2,2,2,1),
- (0,1,1,1,0));
-
- VAR Logo : Array [1..5] of String;
- loop1,loop2,loop3,loop4:integer;
- BEGIN
- pal (13,0,63,0);
- pal (1,0,0,40);
- pal (2,0,0,45);
- pal (3,0,0,50);
- pal (4,0,0,60);
- Logo[1]:=' O OOO OOO O O O O O O OOO O ';
- Logo[2]:='O O O O O O O O O O O O O O';
- Logo[3]:='OOO OOO OOO OOO O O O OOO';
- Logo[4]:='O O O O O O O O O O O O';
- Logo[5]:='O O OOO O O O O O O OOO O O';
- For loop1:=1 to 5 do
- For loop2:=1 to 31 do
- if logo[loop1][loop2]='O' then
- For loop3:=1 to 5 do
- For loop4:=1 to 5 do
- putpixel (loop2*10+loop3,loop1*4+loop4,ball[loop3,loop4],vaddr);
- END;
-
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure RotatePoints (X,Y,Z:Integer);
- { This rotates object lines by X,Y and Z; then places the result in
- TRANSLATED }
- VAR loop1:integer;
- temp:point;
- BEGIN
- For loop1:=1 to maxlines do BEGIN
- temp.x:=lines[loop1,1].x;
- temp.y:=lookup[x,2]*lines[loop1,1].y - lookup[x,1]*lines[loop1,1].z;
- temp.z:=lookup[x,1]*lines[loop1,1].y + lookup[x,2]*lines[loop1,1].z;
-
- translated[loop1,1]:=temp;
-
- If y>0 then BEGIN
- temp.x:=lookup[y,2]*translated[loop1,1].x - lookup[y,1]*translated[loop1,1].y;
- temp.y:=lookup[y,1]*translated[loop1,1].x + lookup[y,2]*translated[loop1,1].y;
- temp.z:=translated[loop1,1].z;
- translated[loop1,1]:=temp;
- END;
-
- If z>0 then BEGIN
- temp.x:=lookup[z,2]*translated[loop1,1].x + lookup[z,1]*translated[loop1,1].z;
- temp.y:=translated[loop1,1].y;
- temp.z:=-lookup[z,1]*translated[loop1,1].x + lookup[z,2]*translated[loop1,1].z;
- translated[loop1,1]:=temp;
- END;
-
- temp.x:=lines[loop1,2].x;
- temp.y:=cos (rad(X))*lines[loop1,2].y - sin (rad(X))*lines[loop1,2].z;
- temp.z:=sin (rad(X))*lines[loop1,2].y + cos (rad(X))*lines[loop1,2].z;
-
- translated[loop1,2]:=temp;
-
- If y>0 then BEGIN
- temp.x:=cos (rad(Y))*translated[loop1,2].x - sin (rad(Y))*translated[loop1,2].y;
- temp.y:=sin (rad(Y))*translated[loop1,2].x + cos (rad(Y))*translated[loop1,2].y;
- temp.z:=translated[loop1,2].z;
- translated[loop1,2]:=temp;
- END;
-
- If z>0 then BEGIN
- temp.x:=cos (rad(Z))*translated[loop1,2].x + sin (rad(Z))*translated[loop1,2].z;
- temp.y:=translated[loop1,2].y;
- temp.z:=-sin (rad(Z))*translated[loop1,2].x + cos (rad(Z))*translated[loop1,2].z;
- translated[loop1,2]:=temp;
- END;
- END;
- END;
-
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure DrawPoints;
- { This draws the translated object to the virtual screen }
- VAR loop1:Integer;
- nx,ny,nx2,ny2:integer;
- temp:integer;
- BEGIN
- For loop1:=1 to MaxLines do BEGIN
- If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0) then BEGIN
- temp:=round (translated[loop1,1].z+zoff);
- nx :=round (256*translated[loop1,1].X) div temp+xoff;
- ny :=round (256*translated[loop1,1].Y) div temp+yoff;
- temp:=round (translated[loop1,2].z+zoff);
- nx2:=round (256*translated[loop1,2].X) div temp+xoff;
- ny2:=round (256*translated[loop1,2].Y) div temp+yoff;
- If (NX > 0) and (NX < 320) and (NY > 25) and (NY < 200) and
- (NX2> 0) and (NX2< 320) and (NY2> 25) and (NY2< 200) then
- line (nx,ny,nx2,ny2,13,vaddr);
- END;
- END;
- END;
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure ClearPoints;
- { This clears the translated object from the virtual screen ... believe it
- or not, this is faster then a straight "cls (vaddr,0)" }
- VAR loop1:Integer;
- nx,ny,nx2,ny2:Integer;
- temp:integer;
- BEGIN
- For loop1:=1 to MaxLines do BEGIN
- If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0) then BEGIN
- temp:=round (translated[loop1,1].z+zoff);
- nx :=round (256*translated[loop1,1].X) div temp+xoff;
- ny :=round (256*translated[loop1,1].Y) div temp+yoff;
- temp:=round (translated[loop1,2].z+zoff);
- nx2:=round (256*translated[loop1,2].X) div temp+xoff;
- ny2:=round (256*translated[loop1,2].Y) div temp+yoff;
- If (NX > 0) and (NX < 320) and (NY > 25) and (NY < 200) and
- (NX2> 0) and (NX2< 320) and (NY2> 25) and (NY2< 200) then
- line (nx,ny,nx2,ny2,0,vaddr);
- END;
- END;
- END;
-
-
- {──────────────────────────────────────────────────────────────────────────}
- Procedure MoveAround;
- { This is the main display procedure. Firstly it brings the object towards
- the viewer by increasing the Zoff, then passes control to the user }
- VAR deg,loop1:integer;
- ch:char;
- BEGIN
- deg:=0;
- ch:=#0;
- Cls (vaddr,0);
- DrawLogo;
- For loop1:=-256 to -40 do BEGIN
- zoff:=loop1*2;
- RotatePoints (deg,deg,deg);
- DrawPoints;
- flip (vaddr,vga);
- ClearPoints;
- deg:=(deg+5) mod 360;
- END;
-
- Repeat
- if keypressed then BEGIN
- ch:=upcase (Readkey);
- Case ch of 'A' : zoff:=zoff+5;
- 'Z' : zoff:=zoff-5;
- ',' : xoff:=xoff-5;
- '.' : xoff:=xoff+5;
- 'S' : yoff:=yoff-5;
- 'X' : yoff:=yoff+5;
- END;
- END;
- DrawPoints;
- flip (vaddr,vga);
- ClearPoints;
- RotatePoints (deg,deg,deg);
- deg:=(deg+5) mod 360;
- Until ch=#27;
- END;
-
-
- BEGIN
- SetUpVirtual;
- Writeln ('Greetings and salutations! Hope you had a great Christmas and New');
- Writeln ('year! ;-) ... Anyway, this tutorial is on 3-D, so this is what is');
- Writeln ('going to happen ... a wireframe square will come towards you.');
- Writeln ('When it gets close, you get control. "A" and "Z" control the Z');
- Writeln ('movement, "," and "." control the X movement, and "S" and "X"');
- Writeln ('control the Y movement. I have not included rotation control, but');
- Writeln ('it should be easy enough to put in yourself ... if you have any');
- Writeln ('hassles, leave me mail.');
- Writeln;
- Writeln ('Read the main text file for ideas on improving this code ... and');
- Writeln ('welcome to the world of 3-D!');
- writeln;
- writeln;
- Write (' Hit any key to contine ...');
- Readkey;
- SetMCGA;
- SetUpPoints;
- MoveAround;
- SetText;
- ShutDown;
- Writeln ('All done. This concludes the eigth sample program in the ASPHYXIA');
- Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
- Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
- Writeln ('Connectix BBS user, and occasionally read RSAProg.');
- Writeln ('For discussion purposes, I am also the moderator of the Programming');
- Writeln ('newsgroup on the For Your Eyes Only BBS.');
- Writeln ('The numbers are available in the main text. You may also write to me at:');
- Writeln (' Grant Smith');
- Writeln (' P.O. Box 270');
- Writeln (' Kloof');
- Writeln (' 3640');
- Writeln ('I hope to hear from you soon!');
- Writeln; Writeln;
- Write ('Hit any key to exit ...');
- Readkey;
- END.